'''
Created on 2010-2-10

@author: summit
'''

import inspect

class AbstractMethod(object):
    '''
    In python language if the method is not overridden, it remains
    possible for a python pragram to call the abstract method. To
    prevent the calling of abstract methods, we introduce the 
    AbstractMethod descriptor class. the idea is to wrap a function
    object that is supposed to be an abstract method in an instance
    of AbstractMethod class as show in Object.py
    '''


    def __init__(self, func):
        '''
        The inspect module provides several useful functions to 
        help get information about live object such as modules,
        classes, methods, functions, tracbacks, frame objects, and
        code objects.
        '''
        
        assert inspect.isfunction(func)
        self._func = func
        
    def __get__(self, obj, type):
        '''
        Python uses the __get__ method of a class bind a method to
        an instance. For example, suppose you have an instance obj
        of some class Cls. When you call a method like this:
        obj.func(*args)
        Python effectively does this:
        meth = __get__(func, obj, Cls)
        meth.__call__(*args)
        '''
        return self.method(obj, self._func, type)
    
    class method(object):
        
        def __init__(self, obj, func, cls):
            self._self = obj
            self._func = func
            self._class = cls
            self.__name__ = func.__name__
        
        def __call__(self, *args, **kwargs):
            msg = "Abstract method %s of class %s called." %(
                    self._func.__name__, self._class.__name__)
            raise TypeError, msg
        
        def __get__(self, *args):
            return self
        